/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

package Project2.cs342.project1.mathNotebook.data;

import java.io.*;
import java.security.*;
import java.security.spec.*;
import javax.crypto.*;
import javax.crypto.spec.*;
import java.util.*;
import java.math.*;
import java.lang.*;
import Project2.cs342.project1.mathNotebook.notebook.NotebookEntry;
/**
 *
 * @author Kevin
 */
public class LocalEncryptionWriter {

     private User user;
     private SecretKey secretKey;
     private String secretKeyString;
     private BigInteger encryptedSecretKey;

    public LocalEncryptionWriter(User user, String password){
        this.user = user;
        this.secretKeyString = password;
        secretKey = generateSecretKey(password);
        encryptedSecretKey = null;
    }


        /**
     * Generates the DES SecretKey object
     *
     * @param DES password as a String
     * @return DES key as a SecretKey object
     */
    public SecretKey generateSecretKey(String password){
        SecretKey desKey = null;
        try{
            byte[] desKeyData = password.getBytes();
            DESKeySpec desKeySpec = new DESKeySpec(desKeyData);
            SecretKeyFactory keyFactory = SecretKeyFactory.getInstance("DES");
            desKey = keyFactory.generateSecret(desKeySpec);


        }
        catch (InvalidKeySpecException e) {System.err.println(e);}
        catch (InvalidKeyException e) {System.err.println(e);}
        catch (NoSuchAlgorithmException e) {
            System.err.println(e);
            e.printStackTrace();
        }


        return desKey;
    }

    /**
     * Encrypts a .gzip file, writes it out as a .encrypt file with the same name and encrypts the DES password using RSA encryption.
     *
     * @param Name of the compressed file as a String
     * @return Boolean of whether or not the write was successful
     */
    public boolean writeEncryptedFile(String compressedFile){

        boolean writeSuccessful= true;
        if(compressedFile.substring(compressedFile.length()-5).equals(".gzip") ){
            try {
                FileInputStream in = new FileInputStream(new File(compressedFile));  //Used to be called fin.
                DataOutputStream dout = null;
                FileOutputStream fout = null;
                Cipher des = null;
                compressedFile = compressedFile.substring(0, (compressedFile.length()-5));
                fout = new FileOutputStream(new File(compressedFile+".encrypt"));

                // Use Data Encryption Standard cipher
                des = Cipher.getInstance("des");
                des.init(Cipher.ENCRYPT_MODE, secretKey);

                dout = new DataOutputStream(fout);

                byte[] input = new byte[in.available()];
                while (true) {
                    int bytesRead = in.read(input);
                    if (bytesRead == -1) break;
                    byte[] output = des.update(input);
                    if (output != null) dout.write(output);
                }


                byte[] output = des.doFinal();
                if (output != null) dout.write(output);
                in.close();
                dout.flush();
                dout.close();

            }

            catch (InvalidKeyException e) {System.err.println(e); writeSuccessful= false;}
            catch (NoSuchAlgorithmException e) {
                System.err.println(e);
                e.printStackTrace();
                writeSuccessful= false;
            }
            catch (NoSuchPaddingException e) {System.err.println(e); writeSuccessful= false;}
            catch (BadPaddingException e) {System.err.println(e); writeSuccessful= false;}
            catch (IllegalBlockSizeException e) {System.err.println(e); writeSuccessful= false;}
            catch (IOException e) {System.err.println(e); writeSuccessful= false;}


            encryptedSecretKey = encryptSecretKey(secretKeyString);

        }
        else{
             writeSuccessful= false;
        }

        return writeSuccessful;

    }


        /**
     * Encrypts the DES password using RSA encryption and the User's public key.
     *
     * @param DES password as a String
     * @return BigInteger value of the encrypted DES password
     */
    private BigInteger encryptSecretKey(String secretKey){

            BigInteger bi = null;

	try {
            InputStream in = new ByteArrayInputStream(secretKey.getBytes() );


            // Use RSA cipher
            KeyFactory keyFactory = KeyFactory.getInstance("rsa");
            Cipher rsa = Cipher.getInstance("rsa");
            Key rsa_pub_key = null;
            X509EncodedKeySpec pubKeySpec = new X509EncodedKeySpec(user.getRsaPublicKey());

            rsa_pub_key = keyFactory.generatePublic(pubKeySpec);
            rsa.init(Cipher.ENCRYPT_MODE, rsa_pub_key);

            ArrayList enc_bytes = new ArrayList();

            byte[] input = new byte[64];
            while (true) {
                int bytesRead = in.read(input);
                if (bytesRead == -1) break;
                byte[] output = rsa.update(input, 0, bytesRead);
                if (output != null)
                    for (int i = 0; i < output.length; i++) enc_bytes.add(new Byte(output[i]));
            }

            byte[] output = rsa.doFinal();
            if (output != null)
                for (int i = 0; i < output.length; i++) enc_bytes.add(new Byte(output[i]));
            in.close();
            Object enc_data_wrap [] =  enc_bytes.toArray();
            byte enc_data [] = new byte [enc_data_wrap.length];
            for (int i = 0; i < enc_data_wrap.length; i++) enc_data[i] = ((Byte)enc_data_wrap[i]).byteValue();
            bi = new BigInteger(enc_data);



        }
        catch (InvalidKeySpecException e) {System.err.println(e);}
        catch (InvalidKeyException e) {System.err.println(e);}
        catch (NoSuchAlgorithmException e) {
            System.err.println(e);
            e.printStackTrace();
        }
        catch (NoSuchPaddingException e) {System.err.println(e);}
        catch (BadPaddingException e) {System.err.println(e);}
        catch (IllegalBlockSizeException e) {System.err.println(e);}
        catch (IOException e) {System.err.println(e);}

        return bi;
    }

     /**
     * Returns the encrypted DES key.
     *
     * @return BigInteger value of the encrypted DES password
     */
    public BigInteger getEncryptedSecretKey(){
        return encryptedSecretKey;
    }

}
